﻿using System;
using SLNGP.Core.GeneticPrograms;
using SLNGP.Core.Individuals;

namespace SLNGP.Core.StopRun
{
    public interface IStopRunConditions
    {
        /// <summary>
        /// Checks the details of the current Genetic Program and determines if the stop conditions have been met. 
        /// </summary>
        /// <returns>true to stop the run, false to continue the run.</returns>
        bool CanStop();

        /// <summary>
        /// Specifies a condition to stop a GP run based on the condition of an individual at the end of the run. 
        /// </summary>
        Func<IIndividual, bool> IndividualStopCondition { get; set; }

        /// <summary>
        /// Returns a value indicating whether the IndividualStopCondition condition has been met. 
        /// Intended to be used when specifying a ComplexStopCondition. 
        /// </summary>
        /// <returns>true if IndividualStopCondition is true, false otherwise.</returns>
        bool? ShouldStopBecauseOfIndividualStopCondition();

        /// <summary>
        /// Gets or sets a condition used to evaluate the Current Generation.
        /// Return True to indicate the condition has been met, false otherwise. 
        /// </summary>
        Func<IGeneration, bool> GenerationStopCondition { get; set; }

        /// <summary>
        /// Returns a value indicating whether the SingleIndividualStop condition has been met. 
        /// Intended to be used when specifying a ComplexStopCondition. 
        /// </summary>
        /// <returns>true if SingleIndividualStop is true, false otherwise.</returns>
        bool? ShouldStopBecauseOfGenerationStopCondition();

        /// <summary>
        /// Gets or sets a custom expression that created complex boolean relationships between the various run conditions. 
        /// Use the IStopRunConditions parameter and create a complex boolean expression between the ShouldX methods. 
        /// </summary>
        Func<IStopRunConditions, bool> ComplexStopCondition { get; set; }

        /// <summary>
        /// Returns a value indicating whether the ComplexStopCondition condition has been met. 
        /// </summary>
        /// <returns>true if ComplexStopCondition is true, false otherwise.</returns>
        bool? ShouldStopBecauseOfComplexStopCondition();


        /// <summary>
        /// Gets or sets a hard limit of the maximum number of generations.
        /// </summary>
        int? MaxGenerationsCount { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether the maximum number of generations have been reached. 
        /// </summary>
        /// <returns></returns>
        bool? ShouldStopBecauseOfMaxGenerationsCount();


        /// <summary>
        /// Determines the relationship between the various specified stop conditions.
        /// </summary>
        StopRunConditionsOpearator StopRunConditionsOpearator { get; set; }

        IGeneticProgram Parent { get; set; }
    }
}